package io.geekidea.boot.util.baiwangApi;

import com.baiwang.open.client.BWRestClient;
import com.baiwang.open.client.IBWClient;
import com.baiwang.open.client.login.BopLoginClient;
import com.baiwang.open.client.login.BopLoginResponse;
import com.baiwang.open.client.login.PasswordLoginClient;
import com.baiwang.open.client.login.PasswordLoginConfig;
import com.baiwang.open.entity.request.SOutputinvoiceFastRedRequest;
import com.baiwang.open.entity.request.node.SOutputinvoiceFastRedDetail;
import com.baiwang.open.entity.response.SOutputinvoiceFastRedResponse;
import com.baiwang.open.exception.BWOpenException;
import io.geekidea.boot.config.baiwang.BaiwangConfig;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 发票快捷红冲
 */
@Component
public class FastRed {
    static String url = BaiwangConfig.getUrl();
    static String appKey = BaiwangConfig.getAppKey();
    static String userName = BaiwangConfig.getUserName();
    static String password = BaiwangConfig.getPassword();
    static String appSecret = BaiwangConfig.getAppSecret();
    static String userSalt = BaiwangConfig.getUserSalt();

    public static SOutputinvoiceFastRedResponse fastRedInvoice(
            String taxNo,//销方税号
            String orderNo,//开票单号（红票）
            String invoiceTerminalCode,//开票终端/数电账号
            String originalSerialNo,//原蓝票请求流水号
            String originalOrderNo,//原蓝票开票单号
            String originalInvoiceCode,
            String originalInvoiceNo,
            String originalDigitInvoiceNo,
            String redInvoiceLabel,//冲红原因
            String entryIdentity,//录入方身份
            String pushEmail//交付邮箱


    ) throws BWOpenException {

        // 非必填：申请方说明（税控票时可选）；可选值：1_1-购方已抵扣，1_2-购方未抵扣，2_0-销方申请（默认），类型String，长度3
        String applyType = "";
        // 非必填：交付手机（用于接收发票交付信息），类型String，长度20
        String pushPhone = "";
        // 非必填：回调地址（红票/红字信息表/红字确认单生成后，平台会回调此地址推送结果），类型String，长度255
        String callBackUrl = "";
        // 非必填：录入方身份（数电票时可选）；可选值：01-销方（默认），02-购方，类型String，长度2
//        String entryIdentity = "";
        // 非必填：冲红原因；可选值：1-销货退回，2-开票有误，3-服务中止，4-发生销售折让，类型String，长度1
//        String redInvoiceLabel = "";

        // 二选一必填：原蓝票请求流水号（与原蓝票开票单号originalOrderNo二选一），类型String，长度20
//        String originalSerialNo = originalSerialNo;//!!!!!!!!!!!!!!!!!!!

        // 二选一必填：原蓝票开票单号（与原蓝票请求流水号originalSerialNo二选一），类型String，长度20
//        String originalOrderNo = "";
        // 税控票必填：原蓝票发票号码（税控票场景下必填，数电票非必填），类型String，长度8
//        String originalInvoiceNo = "";
        // 非必填：快捷冲红类型；可选值：0-普通冲红（仅生成红字信息表/红字确认单），1-快捷冲红（生成后自动开具红票），类型String，长度1
        String fastIssueRedType = "";
        // 非必填：组织机构id（标识当前操作所属的组织机构），类型String，长度32
        String orgId = "";
        // 非必填：开票员id（标识开具红票的操作员），类型String，长度32
        String drawerId = "";

        // 数电票必填：原蓝票数电号码（数电票场景下必填，税控票非必填），类型String，长度20
//        String originalDigitInvoiceNo = "";//
        // 非必填：开票终端/数电账号（标识开票所用的终端或数电账号），类型String，长度30

//        String invoiceTerminalCode = "";
        // 非必填：红票发票种类编码；可选值：01-数电专票，02-数电普票等，类型String，长度3
        String invoiceTypeCode = "";
        // 明细参数：必填：商品税率（需与原蓝票对应商品税率一致），类型String，长度10
        String goodsTaxRate = "";
        // 明细参数：必填：商品不含税金额（需为负数，冲红场景，保留2位小数），类型String，长度16
        String goodsTotalPrice = "";
        // 明细参数：数电红票传明细时必填：原蓝票明细行序号（税控票非必填），类型String，长度4
        String originalInvoiceDetailNo = "";
        // 明细参数：非必填：商品规格型号，类型String，长度40
        String goodsSpecification = "";
        // 明细参数：非必填：商品单价（建议保留小数点后8位以上，开具成品油发票时必填且建议保留5位小数），类型String，长度16
        String goodsPrice = "";
        // 明细参数：非必填：零税率标识；可选值：空-非零税率，1-免税，2-不征税，3-普通零税率，类型String，长度1
        String freeTaxMark = "";
        // 明细参数：非必填：商品数量（需为负数，冲红场景，建议保留小数点后8位以上，开具成品油发票时必填且建议保留5位小数），类型String，长度16
        String goodsQuantity = "";
        // 明细参数：必填：商品税额（需为负数，冲红场景，保留2位小数），类型String，长度16
        String goodsTotalTax = "";
        // 明细参数：非必填：商品单位，类型String，长度20
        String goodsUnit = "";
        // 明细参数：必填：商品税收分类编码（需与原蓝票对应商品分类编码一致），类型String，长度19
        String goodsCode = "";
        // 明细参数：非必填：优惠政策标识；可选值：0-不使用，1-使用，类型String，长度1
        String preferentialMark = "";
        // 明细参数：必填：商品名称（需与原蓝票对应商品名称一致），类型String，长度90
        String goodsName = "";
        // 明细参数：非必填（preferentialMark为1时必填）：优惠政策名称（增值税特殊管理），类型String，长度50
        String vatSpecialManagement = "";
        // 必填：销方税号（标识红票的销售方纳税人识别号），类型String，长度20
//        String taxNo = "338888888888SMB";
        // 非必填：交付邮箱（用于接收发票交付信息），类型String，长度50
//        String pushEmail = "18230059805@163.com";
        // 税控票必填：原蓝票发票代码（税控票场景下必填，数电票非必填），类型String，长度12
//        String originalInvoiceCode = "";

        try {
            String requestId = UUID.randomUUID().toString(); // 生成自定义请求唯一标识（公共参数，非必填，默认UUID，用于追踪请求）
            PasswordLoginConfig loginConfig = new PasswordLoginConfig(); // 初始化密码登录配置对象：封装登录所需的地址、账号、密钥等参数
            loginConfig.setUrl(url); // 设置接口请求地址（与上方初始化的url一致）
            loginConfig.setClientId(appKey); // 必填：设置ClientId：对应appKey（公共参数）
            loginConfig.setClientSecret(appSecret); // 必填：设置ClientSecret：对应appSecret（用于签名验证）
            loginConfig.setUsername(userName); // 必填：设置登录用户名（用于身份验证）
            loginConfig.setPassword(password); // 必填：设置登录密码（用于身份验证）
            loginConfig.setUserSalt(userSalt); // 必填：设置用户盐值（用户身份验证补充字段）

            BopLoginClient loginClient = new PasswordLoginClient(loginConfig); // 初始化密码登录客户端：传入登录配置，用于发起登录请求获取token
            BopLoginResponse loginResponse = loginClient.login(); // 发起登录请求获取token：token用于接口调用前的授权检查（公共参数，必填），token说明参考文档中心->用户授权说明
            // 重载方法：可传入自定义requestId，格式：BopLoginResponse loginResponse = loginClient.login(requestId);

            String token = loginResponse.getResponse().getAccessToken(); // 从登录响应中提取accessToken（后续接口调用需携带此token）

            SOutputinvoiceFastRedRequest request = new SOutputinvoiceFastRedRequest(); // 初始化快捷冲红请求对象：封装快捷冲红接口的所有业务参数

            request.setApplyType(applyType); // 非必填：设置申请方说明（税控票时可选）；可选值：1_1-购方已抵扣，1_2-购方未抵扣，2_0-销方申请（默认），类型String，长度3
//            Map<String, Object> ext = new HashMap<String, Object>(); // 初始化请求扩展字段Map：key为扩展字段别名，value为扩展字段值，非必填
//            request.setExt(ext); // 设置请求扩展字段，非必填
            request.setPushPhone(pushPhone); // 非必填：设置交付手机：用于接收发票交付信息，类型String，长度20
            request.setOrderNo(orderNo); // 必填：设置开票单号（红票）：唯一标识红票开票单据，类型String，长度64
            request.setCallBackUrl(callBackUrl); // 非必填：设置回调地址：红票/红字信息表/红字确认单生成后，平台会回调此地址推送结果，类型String，长度255
            request.setEntryIdentity(entryIdentity); // 非必填：设置录入方身份（数电票时可选）：类型String，长度2；可选值：01-销方（默认），02-购方
            request.setRedInvoiceLabel(redInvoiceLabel); // 非必填：设置冲红原因：类型String，长度1；可选值：1-销货退回，2-开票有误，3-服务中止，4-发生销售折让
            request.setOriginalSerialNo(originalSerialNo); // 二选一必填：设置原蓝票请求流水号：与原蓝票开票单号（originalOrderNo）二选一，类型String，长度20
            request.setOriginalOrderNo(originalOrderNo); // 二选一必填：设置原蓝票开票单号：与原蓝票请求流水号（originalSerialNo）二选一，类型String，长度20
            request.setOriginalInvoiceNo(originalInvoiceNo); // 税控票必填：设置原蓝票发票号码（税控票时必填）：税控票场景下必填，数电票非必填，类型String，长度8
            request.setFastIssueRedType(fastIssueRedType); // 非必填：设置快捷冲红类型：类型String，长度1；可选值：0-普通冲红（仅生成红字信息表/红字确认单），1-快捷冲红（生成后自动开具红票）
            request.setOrgId(orgId); // 非必填：设置组织机构id：类型String，长度32，标识当前操作所属的组织机构
            request.setDrawerId(drawerId); // 非必填：设置开票员id：类型String，长度32，标识开具红票的操作员
            request.setOriginalDigitInvoiceNo(originalDigitInvoiceNo); // 数电票必填：设置原蓝票数电号码（数电票时必填）：数电票场景下必填，税控票非必填，类型String，长度20
            request.setInvoiceTerminalCode(invoiceTerminalCode); // 非必填：设置开票终端/数电账号：类型String，长度30，标识开票所用的终端或数电账号
            request.setInvoiceTypeCode(invoiceTypeCode); // 非必填：设置红票发票种类编码：类型String，长度3；可选值：01-数电专票，02-数电普票，03-数电机动车票，04-数电二手车票，85-数电纸质专票等

            List<SOutputinvoiceFastRedDetail> details = new ArrayList<SOutputinvoiceFastRedDetail>(); // 部分冲红必填：初始化发票明细列表：部分冲红时必填，全量冲红非必填，类型List，最大长度2000
            SOutputinvoiceFastRedDetail sOutputinvoiceFastRedDetail = new SOutputinvoiceFastRedDetail(); // 初始化单个发票明细对象：封装单条商品明细的参数
//            Map<String, Object> ext = new HashMap<String, Object>(); // 初始化明细扩展字段Map：key为扩展字段别名，value为扩展字段值，非必填
//            sOutputinvoiceFastRedDetail.setExt(ext); // 设置明细扩展字段，非必填
            sOutputinvoiceFastRedDetail.setGoodsTaxRate(goodsTaxRate); // 必填：设置商品税率：类型String，长度10，需与原蓝票对应商品税率一致
            sOutputinvoiceFastRedDetail.setGoodsTotalPrice(goodsTotalPrice); // 必填：设置商品不含税金额：类型String，长度16，需为负数（冲红场景），保留2位小数
            sOutputinvoiceFastRedDetail.setOriginalInvoiceDetailNo(originalInvoiceDetailNo); // 数电红票传明细时必填：设置原蓝票明细行序号（数电红票传商品明细时必填）：税控票非必填，类型String，长度4
            sOutputinvoiceFastRedDetail.setGoodsSpecification(goodsSpecification); // 非必填：设置商品规格型号：类型String，长度40
            sOutputinvoiceFastRedDetail.setGoodsPrice(goodsPrice); // 非必填：设置商品单价：类型String，长度16；建议保留小数点后8位以上，开具成品油发票时必填且建议保留5位小数
            sOutputinvoiceFastRedDetail.setFreeTaxMark(freeTaxMark); // 非必填：设置零税率标识：类型String，长度1；可选值：空-非零税率，1-免税，2-不征税，3-普通零税率
            sOutputinvoiceFastRedDetail.setGoodsQuantity(goodsQuantity); // 非必填：设置商品数量：类型String，长度16；需为负数（冲红场景），建议保留小数点后8位以上，开具成品油发票时必填且建议保留5位小数
            sOutputinvoiceFastRedDetail.setGoodsTotalTax(goodsTotalTax); // 必填：设置商品税额：类型String，长度16，需为负数（冲红场景），保留2位小数
            sOutputinvoiceFastRedDetail.setGoodsUnit(goodsUnit); // 非必填：设置商品单位：类型String，长度20
            sOutputinvoiceFastRedDetail.setGoodsCode(goodsCode); // 必填：设置商品税收分类编码：类型String，长度19，需与原蓝票对应商品分类编码一致
            sOutputinvoiceFastRedDetail.setPreferentialMark(preferentialMark); // 非必填：设置优惠政策标识：类型String，长度1；可选值：0-不使用，1-使用
            sOutputinvoiceFastRedDetail.setGoodsName(goodsName); // 必填：设置商品名称：类型String，长度90，需与原蓝票对应商品名称一致
            sOutputinvoiceFastRedDetail.setVatSpecialManagement(vatSpecialManagement); // 非必填（preferentialMark为1时必填）：设置优惠政策名称（增值税特殊管理）：类型String，长度50；可选值：简易征收、稀土产品、免税等

            details.add(sOutputinvoiceFastRedDetail); // 将单个明细添加到明细列表
//            request.setDetails(details); // 将明细列表设置到冲红请求对象

            request.setTaxNo(taxNo); // 必填：设置销方税号：类型String，长度20，标识红票的销售方纳税人识别号
            request.setPushEmail(pushEmail); // 非必填：设置交付邮箱：用于接收发票交付信息，类型String，长度50
            request.setOriginalInvoiceCode(originalInvoiceCode); // 税控票必填：设置原蓝票发票代码（税控票时必填）：税控票场景下必填，数电票非必填，类型String，长度12

            IBWClient client = new BWRestClient(url, appKey, appSecret); // 初始化REST客户端：用于调用百望云开放平台接口，需传入地址、appKey、appSecret（必填）
            // 重载构造方法：传入loginClient，可针对“token错误”异常自动重试1次，非必填，格式：IBWClient client = new BWRestClient(url, appKey, appSecret, loginClient);

            SOutputinvoiceFastRedResponse response = client.sOutputinvoice().fastRed(request, token); // 调用快捷冲红接口（baiwang.s.outputinvoice.fastRed）：传入请求对象、token，获取响应结果
            // 重载方法：可传入自定义requestId，格式：SOutputinvoiceFastRedResponse response = client.sOutputinvoice().fastRed(request, token, requestId);

            System.out.println("response" + response); // 打印接口响应结果（包含红票申请流水号、开票单号等信息）
            return response;
        } catch (BWOpenException e) {

            throw e;
        }
    }
}